using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;

public class MapSystem : PersistentSingleton<MapSystem>
{
    public string seed;

    // 核心数据字典
    public Dictionary<int, List<int>> connections = new Dictionary<int, List<int>>();
    public Dictionary<int, MapItemType> typeDict = new Dictionary<int, MapItemType>();
    public Dictionary<int, Vector3> posDict = new Dictionary<int, Vector3>();
    public Dictionary<int, List<Enemy>> enemyDict = new Dictionary<int, List<Enemy>>();
    public Dictionary<int, List<List<BagItemData>>> winDict = new Dictionary<int, List<List<BagItemData>>>();

    // 节点轴信息（axisId=轴ID，d=轴上距离）
    public Dictionary<int, (int axisId, int d)> nodeAxisInfo = new Dictionary<int, (int axisId, int d)>();
    // 轴方向角度（记录每个axisId对应的方向角度，单位：度）
    public Dictionary<int, float> axisAngles = new Dictionary<int, float>();

    // 定义标准坐标轴的axisId（12个轴中，0°、90°、180°、270°对应的轴）
    private List<int> standardAxisIds = new List<int> { 0, 3, 6, 9 }; // 对应角度：0°、90°、180°、270°

    [SerializeField] private int maxDistanceToConnectOrigin = 2; // 只有d≤2的节点才连接原点
    [SerializeField] private MapView mapView;

    public int nowId;
    public int step;
    public int banStep;
    public int banStepWait;

    /// <summary>
    /// 毒圈顶点节点ID列表（只记录节点ID，不存坐标）
    /// </summary>
    public List<int> poisonVertexIds = new List<int>();

    public void Setup()
    {
        nowId = InfoSystem.Instance.nowMapItemId;
        step = InfoSystem.Instance.mapStep;
        banStep = InfoSystem.Instance.mapBanStep;
        banStepWait = InfoSystem.Instance.mapBanStepWait;
        seed = InfoSystem.Instance.seed;
        int seedValue = seed.Aggregate(0, (acc, c) => acc + c);
        System.Random rng = new System.Random(seedValue);

        ClearAllData();
        GeneratePositions(rng);
        GenerateTypes(rng);
        GenerateConnections();
        GenerateEnemies();
        GenerateRewards();
        PrintAllConnections();
    }

    private void ClearAllData()
    {
        connections.Clear();
        typeDict.Clear();
        posDict.Clear();
        enemyDict.Clear();
        winDict.Clear();
        nodeAxisInfo.Clear();
        axisAngles.Clear();

        // 初始化原点
        posDict[0] = Vector3.zero;
        typeDict[0] = MapItemType.Space;
    }

    private void GeneratePositions(System.Random rng)
    {
        int maxDistance = 8; // 每个轴上的节点数（d=1~8）
        int idCounter = 1;   // 节点ID计数器
        float nodeSpacing = 2f; // 节点间距
        int totalAxes = 12;  // 共12个轴

        // 12个轴按30°均匀分布（axisId=0~11对应角度=0°~330°）
        for (int axisId = 0; axisId < totalAxes; axisId++)
        {
            float angle = axisId * 30f;
            axisAngles[axisId] = angle;

            float rad = angle * Mathf.Deg2Rad;
            Vector3 dir = new Vector3(Mathf.Cos(rad), Mathf.Sin(rad), 0);

            for (int d = 1; d <= maxDistance; d++)
            {
                Vector3 pos = dir * d * nodeSpacing;
                posDict[idCounter] = pos;
                nodeAxisInfo[idCounter] = (axisId, d);
                idCounter++;
            }
        }
    }

    private void GenerateTypes(System.Random rng)
    {
        foreach (var kv in posDict)
        {
            int id = kv.Key;
            if (id == 0)
            {
                typeDict[id] = MapItemType.Space;
                continue;
            }

            if (nodeAxisInfo.TryGetValue(id, out var axisInfo) &&
                standardAxisIds.Contains(axisInfo.axisId))
            {
                typeDict[id] = MapItemType.Space;
            }
            else
            {
                typeDict[id] = rng.NextDouble() < 0.2 ? MapItemType.Fire : MapItemType.Fight;
            }
        }
    }

    private void GenerateConnections()
    {
        connections.Clear();
        int originId = 0;
        connections[originId] = new List<int>();

        Dictionary<int, int> axisFirstNode = new Dictionary<int, int>();
        foreach (var (nodeId, axisInfo) in nodeAxisInfo)
        {
            int axisId = axisInfo.axisId;
            int d = axisInfo.d;
            if (d == 1 && !axisFirstNode.ContainsKey(axisId))
            {
                axisFirstNode[axisId] = nodeId;
                connections[originId].Add(nodeId);
            }
        }

        foreach (var kv in posDict)
        {
            int nodeId = kv.Key;
            if (nodeId == originId) continue;

            if (!nodeAxisInfo.TryGetValue(nodeId, out var axisInfo)) continue;
            int currentAxis = axisInfo.axisId;
            int currentD = axisInfo.d;
            List<int> currentConnections = new List<int>();

            foreach (var (otherNodeId, otherAxisInfo) in nodeAxisInfo)
            {
                if (otherAxisInfo.axisId == currentAxis &&
                    (otherAxisInfo.d == currentD - 1 || otherAxisInfo.d == currentD + 1))
                {
                    currentConnections.Add(otherNodeId);
                }
            }

            float currentAngle = axisAngles[currentAxis];
            List<int> adjacentAxes = axisAngles
                .Where(pair =>
                {
                    int otherAxis = pair.Key;
                    if (otherAxis == currentAxis) return false;
                    float otherAngle = pair.Value;
                    float angleDiff = Mathf.Abs(currentAngle - otherAngle);
                    angleDiff = Mathf.Min(angleDiff, 360f - angleDiff);
                    return angleDiff <= 30f;
                })
                .Select(pair => pair.Key)
                .ToList();

            foreach (int adjAxis in adjacentAxes)
            {
                var targetNode = nodeAxisInfo.FirstOrDefault(kv => kv.Value.axisId == adjAxis && kv.Value.d == currentD);
                if (targetNode.Key != 0) currentConnections.Add(targetNode.Key);
            }

            if (currentD == 1) currentConnections.Add(originId);
            connections[nodeId] = currentConnections.Distinct().ToList();
        }
    }

    private void GenerateEnemies()
    {
        enemyDict.Clear();
        foreach (var kv in typeDict)
        {
            if (kv.Value != MapItemType.Fight) continue;
            int id = kv.Key;
            int count = id % 2 == 0 ? 2 : 1;
            enemyDict[id] = new List<Enemy>();
            for (int i = 0; i < count; i++) enemyDict[id].Add(new Slime());
        }
    }

    private void GenerateRewards()
    {
        winDict.Clear();
        foreach (var kv in typeDict)
        {
            if (kv.Value != MapItemType.Fight) continue;
            int id = kv.Key;
            List<BagItemData> group1 = new List<BagItemData> { new XXZL(), new SJZQ(), new FBDJ() };
            List<BagItemData> group2 = new List<BagItemData> { new Fireball(), new ArrowRain(), new Barricade() };
            winDict[id] = new List<List<BagItemData>> { group1, group2 };
        }
    }

    public void ShowMap()
    {
        mapView.Setup();
        mapView.gameObject.SetActive(true);
    }

    public void PrintAllConnections()
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.AppendLine("=== All Node Connections ===");
        foreach (var id in posDict.Keys.OrderBy(k => k))
        {
            Vector3 pos = posDict[id];
            string typeStr = typeDict.TryGetValue(id, out var type) ? type.ToString() : "Unknown";
            string axisStr = nodeAxisInfo.TryGetValue(id, out var axisInfo)
                ? $"Axis={axisInfo.axisId},D={axisInfo.d},Angle={axisAngles[axisInfo.axisId]:F0}°"
                : "Axis=Origin";
            string nextStr = connections.TryGetValue(id, out var nextIds)
                ? string.Join(",", nextIds.OrderBy(x => x))
                : "";
            sb.AppendLine($"Node {id}: Pos({pos.x:F2},{pos.y:F2}) Type:{typeStr} {axisStr} -> Next: {nextStr}");
        }
        sb.AppendLine("=== End of Connections ===");
        Debug.Log(sb.ToString());
    }

    public void OnEnable()
    {
        ActionSystem.SubscribeReaction<EnterGameGA>(EnterGameGAPost, ReactionTiming.POST);
    }

    public void OnDisable()
    {
        ActionSystem.UnsubscribeReaction<EnterGameGA>(EnterGameGAPost, ReactionTiming.POST);
    }

private void EnterGameGAPost(EnterGameGA ga)
{
    nowId = ga.id;
    step++;
    banStepWait--;
    if (banStepWait == 0)
    {
        banStepWait = 2;
        banStep++;
    }

    InfoSystem.Instance.nowMapItemId = nowId;
    InfoSystem.Instance.mapStep = step;
    InfoSystem.Instance.mapBanStep = banStep;
    InfoSystem.Instance.mapBanStepWait = banStepWait;

    // 更新毒圈顶点
    UpdatePoisonVertexIds();

    // 统一刷新 MapView
    if (mapView != null)
        mapView.RefreshView(); // MapView 内部负责更新可点击节点、英雄位置和毒圈

    InfoSystem.Instance.SaveGame();
}
public void UpdatePoisonVertexIds()
{
    poisonVertexIds.Clear();

    // 按每条轴处理
    Dictionary<int, int> axisMaxDNode = new Dictionary<int, int>();

    foreach (var kv in nodeAxisInfo)
    {
        int nodeId = kv.Key;
        int axisId = kv.Value.axisId;
        int d = kv.Value.d;

        if (d > banStep) continue; // 超过 banStep 的不算

        // 每条轴只保留最大 d 节点
        if (!axisMaxDNode.ContainsKey(axisId) || d > nodeAxisInfo[axisMaxDNode[axisId]].d)
        {
            axisMaxDNode[axisId] = nodeId;
        }
    }

    // 按角度顺时针排序
    poisonVertexIds = axisMaxDNode
        .OrderBy(kv => axisAngles[kv.Key])
        .Select(kv => kv.Value)
        .ToList();

    // 打印调试
    Debug.Log($"[PoisonVertices] banStep={banStep}, IDs: {string.Join(", ", poisonVertexIds)}");
}
}
